/*
 * ADCBoard.h
 *
 *  Created on: May 6, 2010
 *      Author: Mario Rodriguez Huizar
 */

#ifndef ADCBOARD_H_
#define ADCBOARD_H_

#include "ADCQueueManager.h"
#include <assert.h>

#define MAX_ADC_CHANNELS 16  //maximum number of channels in the TS-ADC16

#define SUCCESS						1
#define TSADCSTATUS_DATA			1
#define TSADCSTATUS_NODATA     		0
#define TSADCERR_CANTOPENMEM  		-1
#define TSADCERR_CANTMAPIO16  		-2
#define TSADCERR_CANTMAPIO8   		-3
#define TSADCERR_NOINIT       		-4
#define TSADCERR_HARDWARE     		-5
#define TSADCERR_BADPARAMETER 		-6
#define TSADCERR_QUEUEOVERFLOW 		-7
#define TSADCERR_CANTOPENIRQ6 		-8
#define TSADCERR_CANTOPENIRQ7 		-9
#define TSADCERR_FIFOOVERRUN  		-10
#define TSADCERR_OUTOFMEMORY		-11
#define TSADCERR_MAXERROR			-12
#define TSADCERR_MAXCHANNELERROR	-13

typedef enum {
	ADCRANGE_55S   = 0x0100,  // ADC16: -5 to +5V single ended
	ADCRANGE_05S   = 0x0140,  // ADC16: 0 to +5V  single ended
	ADCRANGE_1010S = 0x0180,  // ADC16: -10 to +10V single ended
	ADCRANGE_0010S = 0x01e0,  // ADC16: 0 to +10V single ended
	ADCRANGE_55D   = 0x0000,  // ADC16: -5 to +5V, differential
	ADCRANGE_05D   = 0x0040,  // ADC16: 0 to +5V (default) differential
	ADCRANGE_1010D = 0x0090,  // ADC16: -10 to +10V differential
	ADCRANGE_0010D = 0x00e0,  // ADC16: 0 to +10V differential
	ADCRANGE_0VS   = 0x0100,  // ADC24: 0 to +VRef (single ended)
	ADCRANGE_02VS  = 0x0140,  // ADC24: 0 to +2xVRef (single ended)
	ADCRANGE_02VAS = 0x0180,  // ADC24: 0 to +2xVRef (single ended)
	ADCRANGE_02VBS = 0x01e0,  // ADC24: 0 to +2xVRef (single ended)
	ADCRANGE_0VD   = 0x0000,  // ADC24: 0 to +VRef (differential)
	ADCRANGE_02VD  = 0x0040,  // ADC24: 0 to +2xVRef (differential)
	ADCRANGE_02VAD = 0x0080,  // ADC24: 0 to +2xVRef (differential)
	ADCRANGE_02VBD = 0x00e0   // ADC24: 0 to +2xVRef (differential)
} adcrange;

typedef enum {
    DACRANGE_0VU   = 0x0000,  // ADC16: 0 to vRef, unbuffered
    DACRANGE_0VB   = 0x1000,  // ADC16: 0 to vRef, buffered
    DACRANGE_02VU  = 0x2000,  // ADC16: 0 to 2 * vRef, unbuffered
    DACRANGE_02VB  = 0x3000   // ADC16: 0 to 2 * vRef, buffered
} dacrefrange;

class ADCBoard {
	const uint32_t myBaseAddr8;
	volatile uint32_t IoBase16;
	volatile uint32_t IoBase8;
	volatile uint16_t *pMappedBaseAddr16;  /* pointer to adc board 16 bit io space */
	volatile uint8_t  *pMappedBaseAddr8;   /* pointer to adc board 8 bit io space */
	bool initialized;   //flag to indicate if the board was initialized
	bool fifoOverflow;  //flag to indicate FIFO overflow
	uint8_t maxChannel; //stores the maximum number of channel to sample 0-15
	uint8_t boardId;
	bool tsadclib16_verboseFlag;
	// Queues for storing the adc packets, one Queue for each channel
	ADCQueueManager *pADCQueues;

	// The data from the FIFO will be stored in ADCPackets.
	// Only when a Packet is full it will copied to the corresponding ADCqueue.
	// The Packet[0] will go to Queue 0, the Packet[1] to Queue 1 and so on...
	ADCPacket myADCPackets[MAX_ADC_CHANNELS];

	static const char *tsadclib16ErrorText[];

public:
	ADCBoard(uint32_t baseAddr, uint32_t baseAddr8, uint8_t portId);
	int8_t initADC(ADCQueueManager *ppRxADCQueues);
	int8_t readFifo(void);
	// Called when we have received a complete ADC packet
	int8_t packetReceiveComplete(uint8_t channel);
	void config(int16_t maxChannel, int32_t sampleRate, adcrange range);
	const char *tsadclib1624_errors(int errorCode);
	void setDACvalue(uint8_t theDacChannel, dacrefrange theRefRange, uint16_t theValue);
	~ADCBoard();
};

#endif //#define ADCBOARD_H_
